//
//  DetailRepo.swift
//  KoiAccounting
//
//  Created by 纪洪文 on 06.04.25.
//

import Foundation
class DetailRepo {
    
    let detailDao = KoiAccountingDB.standard.getDetailDao()
    let categoryDao = KoiAccountingDB.standard.getCategoryDao()
    let bookDao = KoiAccountingDB.standard.getBookDao()
    
    func loadDetail(recordId: String, uid: String, bookId: String) -> AccountingDetailCombine? {
        let detail = detailDao.getDetailRecord(recordId: recordId, uid: uid, bookId: bookId)
        let category = categoryDao.getCategoryByCid(cid: detail?.cid ?? "", uid: uid, bookId: bookId)
        let book = bookDao.getBook(uid: uid, bookId: bookId)
        if let detail = detail , let category = category, let book = book {
            return AccountingDetailCombine(id: detail.id ?? 0, detail: detail, category: category, book: book)
        }
        return nil
    }
    
    func saveRecord(accountingDetail: AccountingDetail) {
        detailDao.saveRecord(accountingDetail: accountingDetail)
    }
    
    func updateCategory(accountingDetail: AccountingDetail) {
        
    }
    
    func getPieDataByWeekDays(weekDays: Array<String>, categoryType: String, uid: String, bookId: String) -> Array<CategoryAmount> {
        let dataList = detailDao.getPieDataByWeekDays(weekDays: weekDays, categoryType: categoryType, uid: uid, bookId: bookId)
        let parentDataList = dataList.filter({ $0.category.parentId == nil })
        let subDataList = dataList.filter({ $0.category.parentId != nil })
        let parentCidList = dataList.map{ $0.category.parentId.orEmpty }
        
        let allParentCategoryList = categoryDao.getCategoryListByCids(uid: uid, bookId: bookId, cids: parentCidList)
        var parentCategoryMap = [String: AccountingCategory]()
        allParentCategoryList.forEach { category in
            parentCategoryMap[category.cid.orEmpty] = category
        }
        var resultParentMap = [String: CategoryAmount]()
        
        subDataList.forEach { data in
            let parentId = data.category.parentId.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                var parentCategory = parentCategoryMap[parentId]!
                parentCategory.hasSubCategory = true
                resultParentMap[parentId] = CategoryAmount(category: parentCategory, amount: data.amount, percent: 0.0)
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        parentDataList.forEach { data in
            let parentId = data.category.cid.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                resultParentMap[parentId] = data
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        return resultParentMap.values.map{ $0 }.sorted{ $0.amount > $1.amount }
    }
    
    func getWeekPieDataByCid(weekDays: Array<String>, categoryType: String, cid: String, uid: String, bookId: String) -> [CategoryAmount] {
        let subCategoryList = categoryDao.getSubCategoryListByParentId(uid: uid, bookId: bookId, parentId: cid)
        let subCidList = subCategoryList.map{ $0.cid.orEmpty }
        let categoryAmountList = detailDao.getPieDataByWeekDays(weekDays: weekDays, categoryType: categoryType, uid: uid, bookId: bookId, cids: [cid])
        
        let subCategoryAmountList = detailDao.getPieDataByWeekDays(weekDays: weekDays, categoryType: categoryType, uid: uid, bookId: bookId, cids: subCidList)
        
        let resultList = categoryAmountList + subCategoryAmountList
        
        return resultList
    }
    
    func getPieDataByMonth(month: String, categoryType: String, uid: String, bookId: String) -> Array<CategoryAmount> {
        let dataList = detailDao.getPieDataByMonth(month: month, categoryType: categoryType, uid: uid, bookId: bookId)
        let parentDataList = dataList.filter({ $0.category.parentId == nil })
        let subDataList = dataList.filter({ $0.category.parentId != nil })
        let parentCidList = dataList.map{ $0.category.parentId.orEmpty }
        
        let allParentCategoryList = categoryDao.getCategoryListByCids(uid: uid, bookId: bookId, cids: parentCidList)
        var parentCategoryMap = [String: AccountingCategory]()
        allParentCategoryList.forEach { category in
            parentCategoryMap[category.cid.orEmpty] = category
        }
        var resultParentMap = [String: CategoryAmount]()
        
        subDataList.forEach { data in
            let parentId = data.category.parentId.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                var parentCategory = parentCategoryMap[parentId]!
                parentCategory.hasSubCategory = true
                resultParentMap[parentId] = CategoryAmount(category: parentCategory, amount: data.amount, percent: 0.0)
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        parentDataList.forEach { data in
            let parentId = data.category.cid.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                resultParentMap[parentId] = data
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        return resultParentMap.values.map{ $0 }.sorted{ $0.amount > $1.amount }
    }
    
    func getMonthPieDataByCid(month: String, categoryType: String, cid: String, uid: String, bookId: String) -> [CategoryAmount] {
        let subCategoryList = categoryDao.getSubCategoryListByParentId(uid: uid, bookId: bookId, parentId: cid)
        let subCidList = subCategoryList.map{ $0.cid.orEmpty }
        let categoryAmountList = detailDao.getPieDataByMonth(month: month, categoryType: categoryType, uid: uid, bookId: bookId, cids: [cid])
        
        let subCategoryAmountList = detailDao.getPieDataByMonth(month: month, categoryType: categoryType, uid: uid, bookId: bookId, cids: subCidList)
        
        let resultList = categoryAmountList + subCategoryAmountList
        
        return resultList
    }
    
    func getPieDataByYear(year: String, categoryType: String, uid: String, bookId: String) -> Array<CategoryAmount> {
        let dataList = detailDao.getPieDataByYear(year: year, categoryType: categoryType, uid: uid, bookId: bookId)
        let parentDataList = dataList.filter({ $0.category.parentId == nil })
        let subDataList = dataList.filter({ $0.category.parentId != nil })
        let parentCidList = dataList.map{ $0.category.parentId.orEmpty }
        
        let allParentCategoryList = categoryDao.getCategoryListByCids(uid: uid, bookId: bookId, cids: parentCidList)
        var parentCategoryMap = [String: AccountingCategory]()
        allParentCategoryList.forEach { category in
            parentCategoryMap[category.cid.orEmpty] = category
        }
        var resultParentMap = [String: CategoryAmount]()
        
        subDataList.forEach { data in
            let parentId = data.category.parentId.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                var parentCategory = parentCategoryMap[parentId]!
                parentCategory.hasSubCategory = true
                resultParentMap[parentId] = CategoryAmount(category: parentCategory, amount: data.amount, percent: 0.0)
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        parentDataList.forEach { data in
            let parentId = data.category.cid.orEmpty
            let categoryAmount = resultParentMap[parentId]
            if (categoryAmount == nil) {
                resultParentMap[parentId] = data
            } else {
                resultParentMap[parentId]?.amount = (categoryAmount?.amount ?? 0.0) + (data.amount)
            }
        }
        
        return resultParentMap.values.map{ $0 }.sorted{ $0.amount > $1.amount }
    }
    
    func getYearPieDataByCid(year: String, categoryType: String, cid: String, uid: String, bookId: String) -> [CategoryAmount] {
        let subCategoryList = categoryDao.getSubCategoryListByParentId(uid: uid, bookId: bookId, parentId: cid)
        let subCidList = subCategoryList.map{ $0.cid.orEmpty }
        let categoryAmountList = detailDao.getPieDataByYear(year: year, categoryType: categoryType, uid: uid, bookId: bookId, cids: [cid])
        
        let subCategoryAmountList = detailDao.getPieDataByYear(year: year, categoryType: categoryType, uid: uid, bookId: bookId, cids: subCidList)
        
        let resultList = categoryAmountList + subCategoryAmountList
        
        return resultList
    }
}
